package com.lambkit.spring.service;

import com.lambkit.core.BeanContainer;
import com.lambkit.core.service.BeanFactory;
import org.springframework.context.ApplicationContext;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author yangyong(孤竹行)
 */
public class SpringBeanFactory implements BeanFactory {

    private BeanContainer beanContainer = new BeanContainer();

    private ApplicationContext applicationContext;

    public SpringBeanFactory(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    @Override
    public <T> T get(Class<T> clazz) {
        T bean = beanContainer.getBean(clazz);
        if(bean == null) {
            bean = applicationContext.getBean(clazz);
            //beanContainer.addBean(clazz, bean);
        }
        return bean;
    }

    @Override
    public <T> void set(Class<T> clazz, T bean) {
        beanContainer.addBean(clazz, bean);
    }

    @Override
    public <T> void set(Class<T> interfaceClass, Class<? extends T>... implementClass) {
        beanContainer.addImpl(interfaceClass, implementClass);
    }

    @Override
    public <T> T getBean(Class<T> clazz) throws Exception {
        return get(clazz);
    }

    @Override
    public <T> Map<String, T> getBeansMapOfType(Class<T> clazz) throws Exception {
        Map<String, T> beanMap =  applicationContext.getBeansOfType(clazz);
        T bean = beanContainer.getBean(clazz);
        if(bean != null) {
            beanMap.put(clazz.getName(), bean);
            return beanMap;
        }
        return null;
    }

    @Override
    public <T> List<T> getBeansOfType(Class<T> type) throws Exception {
        Map<String, T> beans = applicationContext.getBeansOfType(type);
        List<T> list = new ArrayList<>();
        if(beans == null) {
            return list;
        }
        for (T bpp : beans.values()) {
            list.add(bpp);
        }
        T bean = beanContainer.getBean(type);
        if(bean != null) {
            list.add(bean);
        }
        return list;
    }
}
